package fi.hell.lunchit

import grails.test.*
import fi.hell.lunchit.testing.DomainFactory
import fi.hell.enums.*

class UserIntegrationTests extends GrailsUnitTestCase {
    
	void setUp() {
		super.setUp()
		
		mockConfig '''
            restaurant.logo.width = 250
            restaurant.logo.height = 114
        '''
    }

    void tearDown() {
    	super.tearDown()
    }

    void testFavouritRestaurants() {
    	Restaurant r1 = DomainFactory.getRestaurant()
    	Restaurant r2 = DomainFactory.getRestaurant()
    	User u1 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	u1.save()

    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(u1.hasErrors())
    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u1
    	rnd2.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd2.selection = r2
    	rnd2.price = 500
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u1
    	rnd3.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.save()

    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())
    	
    	Map<Restaurant, Integer> assertedFavourites = [
    	    (r2):2,
    	    (r1):1
    	]

    	assertEquals(assertedFavourites, u1.favouritRestaurants())
    	    
	    Round rnd4 = new Round()
    	rnd4.user = u1
    	rnd4.day = DomainFactory.getRoundDay(2010,01,04)
    	rnd4.selection = r1
    	rnd4.price = 1000
    	rnd4.save()
    	
    	Round rnd5 = new Round()
    	rnd5.user = u1
    	rnd5.day = DomainFactory.getRoundDay(2010,01,05)
    	rnd5.selection = r1
    	rnd5.price = 1000
    	rnd5.save()

    	assertFalse(rnd4.hasErrors())
    	assertFalse(rnd5.hasErrors())
    	
    	assertedFavourites = [
    	    (r1):3,
    	    (r2):2
    	]
    	
    	assertEquals(assertedFavourites, u1.favouritRestaurants())
    }
    
    void testMoneyUsed() {
    	Restaurant r1 = DomainFactory.getRestaurant()
    	Restaurant r2 = DomainFactory.getRestaurant()
    	User u1 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	u1.save()

    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(u1.hasErrors())
    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u1
    	rnd2.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd2.selection = r2
    	rnd2.price = 500
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u1
    	rnd3.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.save()

    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())

    	assertEquals(2000, u1.moneyUsed())
    	    
	    Round rnd4 = new Round()
    	rnd4.user = u1
    	rnd4.day = DomainFactory.getRoundDay(2010,01,04)
    	rnd4.selection = r1
    	rnd4.price = 1000
    	rnd4.save()
    	
    	Round rnd5 = new Round()
    	rnd5.user = u1
    	rnd5.day = DomainFactory.getRoundDay(2010,01,05)
    	rnd5.selection = r1
    	rnd5.price = 1000
    	rnd5.save()

    	assertFalse(rnd4.hasErrors())
    	assertFalse(rnd5.hasErrors())
    	
    	assertEquals(4000, u1.moneyUsed())
    }
    
    void testTotalExpenditures() {
    	Restaurant r1 = DomainFactory.getRestaurant()
    	Restaurant r2 = DomainFactory.getRestaurant()
    	User u1 = DomainFactory.getUser()
    	User u2 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	u1.save()
    	u2.save()
    	
    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(u1.hasErrors())
    	assertFalse(u2.hasErrors())
    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u1
    	rnd2.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd2.selection = r2
    	rnd2.price = 800
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u2
    	rnd3.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.save()
    	
    	Round rnd4 = new Round()
    	rnd4.user = u2
    	rnd4.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd4.selection = r1
    	rnd4.price = 1000
    	rnd4.save()

    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())
    	assertFalse(rnd4.hasErrors())
    	
    	Map<User, Integer> assertedMap = [
    	      (u1):1800,
    	      (u2):1500
    	]
    	assertEquals(assertedMap, User.totalExpenditures())

        assertedMap = [
    	      (u2):1500,
    	      (u1):1800
    	]
        assertEquals(assertedMap, User.totalExpenditures(5, "asc"))

    	Round rnd5 = new Round()
    	rnd5.user = u1
    	rnd5.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd5.selection = r1
    	rnd5.price = 200
    	rnd5.save()
    	
    	Round rnd6 = new Round()
    	rnd6.user = u2
    	rnd6.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd6.selection = r1
    	rnd6.price = 1000
    	rnd6.save()

    	assertFalse(rnd5.hasErrors())
    	assertFalse(rnd6.hasErrors())
    	
    	assertedMap = [
    	      (u2):2500,
    	      (u1):2000
    	]
    	assertEquals(assertedMap, User.totalExpenditures())
    }
    
    void testAverageExpenditures() {
    	Restaurant r1 = DomainFactory.getRestaurant()
    	Restaurant r2 = DomainFactory.getRestaurant()
    	User u1 = DomainFactory.getUser()
    	User u2 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	u1.save()
    	u2.save()
    	
    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(u1.hasErrors())
    	assertFalse(u2.hasErrors())
    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u1
    	rnd2.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd2.selection = r2
    	rnd2.price = 800
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u2
    	rnd3.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.save()
    	
    	Round rnd4 = new Round()
    	rnd4.user = u2
    	rnd4.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd4.selection = r1
    	rnd4.price = 1000
    	rnd4.save()

    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())
    	assertFalse(rnd4.hasErrors())
    	
    	Map<User, Integer> assertedMap = [
    	      (u1):900,
    	      (u2):750
    	]
    	assertEquals(assertedMap, User.averageExpenditures())

        assertedMap = [
    	      (u2):750,
    	      (u1):900
    	]
        assertEquals(assertedMap, User.averageExpenditures(5, "asc"))

    	Round rnd5 = new Round()
    	rnd5.user = u1
    	rnd5.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd5.selection = r1
    	rnd5.price = 300
    	rnd5.save()
    	
    	Round rnd6 = new Round()
    	rnd6.user = u2
    	rnd6.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd6.selection = r1
    	rnd6.price = 1200
    	rnd6.save()

    	assertFalse(rnd5.hasErrors())
    	assertFalse(rnd6.hasErrors())
    	
    	assertedMap = [
    	      (u2):900,
    	      (u1):700
    	]
    	assertEquals(assertedMap, User.averageExpenditures())
    }
    
    void testMostVotedRestaurants() {
    	Restaurant r1 = DomainFactory.getRestaurant()
    	Restaurant r2 = DomainFactory.getRestaurant()
    	User u1 = DomainFactory.getUser()
    	User u2 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	u1.save()
    	u2.save()
    	
    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(u1.hasErrors())
    	assertFalse(u2.hasErrors())
    	
    	Vote v1 = new Vote([vote:3, restaurant:r1])
    	Vote v2 = new Vote([vote:3, restaurant:r1])
    	Vote v3 = new Vote([vote:2, restaurant:r2])
    	Vote v4 = new Vote([vote:3, restaurant:r2])
    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.addToVotes(v1)
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u1
    	rnd2.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd2.selection = r2
    	rnd2.price = 800
    	rnd2.addToVotes(v2).addToVotes(v3)
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u2
    	rnd3.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.addToVotes(v4)
    	rnd3.save()
    	
    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())
    	
    	Map<Restaurant, Integer> assertedMap = [
            (r1):6,
            (r2):2
	    ]
    	
    	assertEquals(assertedMap, u1.mostVotedRestaurants())
            
        assertedMap = [
           (r2):3
   	    ]
    	assertEquals(assertedMap, u2.mostVotedRestaurants())
    }
    
    void testMostSelectionsByTag() {
    	RestaurantTag rt1 = new RestaurantTag([name:"BURGER"])
    	RestaurantTag rt2 = new RestaurantTag([name:"PIZZA"])
    	RestaurantTag rt3 = new RestaurantTag([name:"TAKEAWAY"])
    	RestaurantTag rt4 = new RestaurantTag([name:"ORIENTAL"])
    	RestaurantTag rt5 = new RestaurantTag([name:"VEGETARIAN"])
    	RestaurantTag rt6 = new RestaurantTag([name:"PASTA"])
    	RestaurantTag rt7 = new RestaurantTag([name:"FASTFOOD"])
    	
    	Restaurant r1 = DomainFactory.getRestaurant()
    	r1.addToTags(rt1).addToTags(rt3).addToTags(rt7)
    	Restaurant r2 = DomainFactory.getRestaurant()
    	r2.addToTags(rt2).addToTags(rt6).addToTags(rt7).addToTags(rt3)
    	Restaurant r3 = DomainFactory.getRestaurant([tags:[rt4, rt5, rt3]])
    	r3.addToTags(rt4).addToTags(rt5).addToTags(rt3)
    	User u1 = DomainFactory.getUser()
    	User u2 = DomainFactory.getUser()
    	r1.save()
    	r2.save()
    	r3.save()
    	u1.save()
    	u2.save()
    	
    	assertFalse(r1.hasErrors())
    	assertFalse(r2.hasErrors())
    	assertFalse(r3.hasErrors())
    	assertFalse(u1.hasErrors())
    	assertFalse(u2.hasErrors())

    	
    	Round rnd1 = new Round()
    	rnd1.user = u1
    	rnd1.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd1.selection = r1
    	rnd1.price = 1000
    	rnd1.save()
    	
    	Round rnd2 = new Round()
    	rnd2.user = u2
    	rnd2.day = DomainFactory.getRoundDay(2010,01,01)
    	rnd2.selection = r3
    	rnd2.price = 800
    	rnd2.save()
    	
    	Round rnd3 = new Round()
    	rnd3.user = u1
    	rnd3.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd3.selection = r2
    	rnd3.price = 500
    	rnd3.save()
    	
    	Round rnd4 = new Round()
    	rnd4.user = u2
    	rnd4.day = DomainFactory.getRoundDay(2010,01,02)
    	rnd4.selection = r3
    	rnd4.price = 500
    	rnd4.save()
    	
    	Round rnd5 = new Round()
    	rnd5.user = u1
    	rnd5.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd5.selection = r1
    	rnd5.price = 500
    	rnd5.save()
    	
    	Round rnd6 = new Round()
    	rnd6.user = u2
    	rnd6.day = DomainFactory.getRoundDay(2010,01,03)
    	rnd6.selection = r1
    	rnd6.price = 500
    	rnd6.save()
    	
    	assertFalse(rnd1.hasErrors())
    	assertFalse(rnd2.hasErrors())
    	assertFalse(rnd3.hasErrors())
    	assertFalse(rnd4.hasErrors())
    	assertFalse(rnd5.hasErrors())
    	assertFalse(rnd6.hasErrors())

    	// u1 eaten 2 times in burger place
    	Map<User, Integer> assertMap = [
    	    (u1):2
    	]
    	assertEquals(assertMap, User.mostSelectionsByTagName(rt1.name, 1))
    	
    	// u1 eaten 1 times in pizza place
    	assertMap = [
     	    (u1):1
     	]
    	assertEquals(assertMap, User.mostSelectionsByTagName(rt2.name, 1))
    	
    	// u1 eaten 3 times in take away place
    	assertMap = [
      	    (u1):3
      	]
    	assertEquals(assertMap, User.mostSelectionsByTagName(rt3.name, 1))
    	
    	// u2 eaten 2 times in oriental place
    	assertMap = [
      	    (u2):2
      	]
    	assertEquals(assertMap, User.mostSelectionsByTagName(rt4.name, 1))
    	
      	// u2 eaten 2 times in vegetarian place
    	assertMap = [
     	    (u2):2
     	]
    	assertEquals(assertMap, User.mostSelectionsByTagName(rt5.name, 1))
    }
}

